Welcome to Week 1

Congratulations on starting the course! Before you tackle the assignments for Week 1, please make sure you have completed all the instructions under “Before the Course: Get your toolbox set up” on the Course Intro page. If you have any trouble getting R, RStudio, and GitHub set up, please reach out to the instructor immediately so that we can get you on track.

If you have completed the set up instructions in the Course Intro, please watch the video below, which gives a nice introduction to Systems Thinking, which is very helpful when using GIS for Sustainability and Resilience.

Systems Thinking 101

embed_url("https://www.youtube.com/watch?v=bNASybOzruM&t=218s")

GIS for Sustainability and Resilience

For an introduction to the ideas of sustainability and resilience, and how GIS can be used to help us understand them, please read the following short articles (you don’t have to watch the embedded videos or follow the embedded links, but please do if they are of interest to you):

Resilience and Sustainability: the Definitions

Resilience: a Sustainability Prerequisite

Resilient and Sustainable Future with GIS

Getting started in R

There are many GIS tools you can use to support sustainability and resilience. In this course, we are using R (and RStudio). There are many reasons for this choice, but some of the most important are:

  • It is free!!
  • It creates reproducible code that can be shared and validated
  • It can be used for all kinds of data analysis and visualization, not just spatial

For a brief introduction to using R, please read Chapter 2: Introducing R and RStudio in the free ebook Data Analysis and Processing with R based on IBIS data.

Introducing R and RStudio

Now, let’s get started with some basics of using R.

First, create a new R Markdown file and name it “GISSR_W1_Your_Name”, using your own name. This is where you will follow the tutorials and complete the weekly challenges. The instructor will use this file to track your progress and see if you need help.

R Tutorial and Mini-challenges

Follow the tutorial available here: Intro to R

The rmarkdown is available within this project: intro_to_r.rmd.

Getting started with GIS in R

Before we jump into doing GIS, it’s important to understand some basics about what GIS is and how spatial data works.

Watch this video from the GIS Lecture Series by Christopher McGinty at Utah State University.

embed_url("https://www.youtube.com/watch?v=FrTvGpK95U4&t=7s")

Please read the following short chapter in the free, online textbook Intro to GIS and Spatial Analysis by Manuel Gimond.

Chapter 1 Introduction to GIS

Watch this video from the GIS Lecture Series by Christopher McGinty at Utah State University.

embed_url("https://www.youtube.com/watch?v=6KfbrjX_PHA&list=PLqISefT_qzxIncMoWqqDfER8bfZk4q0BE&index=9")

Please read the following short chapter in the free, online textbook Intro to GIS and Spatial Analysis by Manuel Gimond.

Chapter 2 Feature Representation

Watch this video from the GIS Lecture Series by Christopher McGinty at Utah State University. Keep in mind that in this course, we are focusing on vector data. In the future, we hope to offer a class that focuses on raster data.

embed_url("https://www.youtube.com/watch?v=afHlxZaCyFw&list=PLqISefT_qzxIncMoWqqDfER8bfZk4q0BE&index=8")

Please read the following short chapter in the free, online textbook Intro to GIS and Spatial Analysis by Manuel Gimond.

Chapter 9 Coordinate Systems

Assignment: Visualizing Spatial Data Tutorial

This week’s three tutorials and accompanying challenges will get you making maps, creating your own (small) datasets, and using APIs to retrieve data.

Follow each tutorial below, and create a new R chunk in your new R Markdown file (that you created for the Intro to R tutorial above) for each chunk in the tutorial. You can copy and paste the code directly, but be sure to take the time to look at the code and try to understand what it is telling your computer to do. If you have any questions, write them down and bring them to office hours so we can discuss, or you can include your questions in your RMarkdown file and push your code to our GitHub classroom (be sure to say in your commit message that you need help with a particular part or question!).

This tutorial will help you get started with basic mapping using the Rnaturalearth package. This packages allows us to retrieve data from Natural Earth, a free and open geospatial data repository with global coverage.

Set up your environment

First, you will need to install (if you haven’t already) and load all the packages we use in this tutorial.

Packages required for this tutorial:

  • tidyverse (which includes ggplot2, more info available here)

  • sf (more info available here and here)

  • rnaturalearth (more info availablehere)

  • rnaturalearthdata (this provides more data, and higher resolution data)

  • rnaturalearthhires (this provides the highest resolution data, which is best for mapping small areas)

Refer back to the Welcome to R tutorial if you need a reminder on how to do this.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()  masks stats::filter()
## ✖ lubridate::hms() masks vembedr::hms()
## ✖ dplyr::lag()     masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sf)
## Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(rnaturalearth)
library(rnaturalearthdata)
## 
## Attaching package: 'rnaturalearthdata'
## 
## The following object is masked from 'package:rnaturalearth':
## 
##     countries110
library(rnaturalearthhires)

Create your first world map

In the code chunk below, we are creating a spatial dataframe object of the countries of the world, at a medium resolution scale. We use the ne_countries function to retrieve data on countries from the Natural Earth data repository.

We are assigning the name world to this object.

In the second line, we are checking to see that the object is the correct “class” of object. Once you run the code chunk (using the green arrow at the top right of the code chunk), the output should read [1] "sf" "data.frame", which tells us that the object named world is a simple features data frame, which is what we want!

world <- ne_countries(scale = "medium", returnclass = "sf")
class(world)
## [1] "sf"         "data.frame"

You should also see in your environment frame that there is now an object called world and it should have 242 obs. (which stands for observations) of 169 variables. Click on the word world in your environment pane to see the data frame in its own tab within RStudio. You can see which countries are included (the rows of the dataframe) and which variables are included (the columns of the dataframe). We can now use this dataframe to make maps!

The code chunk below uses the function ggplot to create a data visualization of our dataset. We have to tell R what dataset we want to use (data = world), and then we add a + to extend our function to a new line and tell R that we want a map (geom_sf()).

ggplot(data = world) +
    geom_sf()

It may not be fancy, but we made a map of the world! Now let’s make some improvements.

First, let’s add a new line to our ggplot function that adds labels to our x and y axes, using xlab and ylab. Our x axis represents Longitude, and our y axis represents Latitude, so let’s label them that way. Feel free to change the labels to another language if you want!

(For world maps, people usually either know that the axes represent Latitude and Longitude, or they don’t care. So we won’t add it in the rest of our maps today, but you know how to for when it makes sense to include them.)

ggplot(data = world) +
    geom_sf() +
    xlab("Longitude") + ylab("Latitude") 

Now let’s add a title and subtitle to our map.

Challenge 1: Change the subtitle in the code to your name instead of mine. Feel free to change the title and subtitle to another language!

ggplot(data = world) +
    geom_sf() +
    ggtitle("Countries of the World", subtitle = "Created by Catherine Brockway")

Improve your world map

Remove data

Let’s now remove Antarctica from our map, since it takes up a lot of space, and it’s not a “country” per se. This is just an example of how to change your underlying data to alter a map. Whether or not to include Antarctica is a choice you will make for each world map depending on the purpose of the map. This is our first time cleaning our dataframe, and we are using a function from the tidyverse package called filter.

If you take another look at our world dataframe, there is a column called iso_a3. This column includes ISO alpha-3 (or 3 letter codes) for each country. You can read more about ISO alpha-3 codes here. The code for Antarctica is ATA, so we want to create a new dataframe that excludes the row that has ATA in the iso_a3 column. To do this, we use the code filter(iso_a3 != "ATA"), where the != means “is not”.

We are also using the %>% symbol for the first time, which is called a “pipe”. You can learn more about how to use pipes here. They are very useful for making complex changes to our dataframes, so we’ll be using them a lot!

The code chunk below will create a new dataframe called world_without_antarctica from our existing dataframe called world. Notice that in your environment pane, you now have a new object with one less observation than the original, but with the same number of variables.

Challenge 2: Instead of removing antarctica, remove Australia from the map. Remember to change the name of the dataframe to something like world_without_Australia.

Nothing against Australia! We’re just learning how to navigate dataframes and make choices about our maps.

world_without_antarctica <- world %>% 
  filter(iso_a3 != "ATA")

Then we create a new use of the ggplot() function that specifies our new dataframe without Antarctica. Notice this code is slightly different in terms of where the data = world_without_antarctica part shows up. This is one of many examples where there are multiple ways of doing the same thing in R. It’s a matter of style, and you will develop your own preferred style as you learn more.

ggplot() + 
  geom_sf(data = world_without_antarctica)

Okay, now let’s add in titles the way we learned about earlier for our new map.

ggplot() + 
  geom_sf(data = world_without_antarctica) +
    ggtitle("Countries of the World", subtitle = "without Antarctica")

Map aesthetics

Now let’s work on making our map pretty with some colors. Inside our geom_sf() parentheses, we can add our own colors to our map. The argument fill add color to our polygons, and color is the color of our lines. size refers to the size of our lines.

The colors we are using here are what are known as “hex colors”, because they are designated with 6 numbers (hexadecimal) after a # sign. This is how html (websites) code colors. Use this site to find more colors and their hex codes.

Challenge 3: Try out different colors on your map until you find a combination that you like.

ggplot() + 
  geom_sf(data = world_without_antarctica, 
          fill = "#669438", color = "#32481B", size = 0.25) +
  ggtitle("Countries of the World", subtitle = "without Antarctica")

Now let’s work on an important aspect of cartographic design: decluttering our map. Since we are just making a basic world map, let’s get rid of the grid lines showing latitude and longitude and the box around our map. The easiest way to do this is to use a theme that is built in to the ggplot2 package: theme_void.

ggplot() + 
  geom_sf(data = world_without_antarctica, 
          fill = "#669438", color = "#32481B", size = 0.25) +
  ggtitle("Countries of the World", subtitle = "without Antarctica")+
  theme_void()

We can also use our variables (columns in our dataframe) to add color to each country. The Natural Earth dataset happens to come with some columns with a coloring scheme with 7–13 colors (mapcolor7, mapcolor9, etc.) so that no countries with a shared border share a color. We can “fill” our country polygons with colors using that column mapcolor7.

Notice that the mapcolor7 column only provides numbers, so we need to add a color scale, or palette, to associate with the numbers. This is similar to what we will do when we start making choropleth maps using variables with data about countries. Since our data is categorical (also known as discrete or qualitative) in this case, we want to use a color palette that is designed for use with discrete data.

Challenge 4: Try a few different discrete color palettes and choose one that you like.

We are using Brewer color palettes (created by Cynthia A. Brewer) in this class, which are designed specifically for map-making.

To learn more about choosing color palettes in R, specifically using the ggplot2 package, read Chapter 11 in “ggplot2: Elegant Graphics for Data Analysis”.

ggplot() + 
  geom_sf(data = world_without_antarctica, 
          aes(fill = as.factor(mapcolor7)),
          color = "#401D16", size = 0.25) +
  scale_fill_brewer(palette = "Set1") +
  guides(fill = "none") +
  theme_void()

Changing your map CRS

As a cartographer, you need to choose the best Coordinate Reference System (CRS) for your map. First, let’s figure out what projection our current world map is in. This is the projection that is embedded in the Natural Earth data we retrieved. We use the st_crs function to see the current CRS.

st_crs(world_without_antarctica)
## Coordinate Reference System:
##   User input: WGS 84 
##   wkt:
## GEOGCRS["WGS 84",
##     DATUM["World Geodetic System 1984",
##         ELLIPSOID["WGS 84",6378137,298.257223563,
##             LENGTHUNIT["metre",1]]],
##     PRIMEM["Greenwich",0,
##         ANGLEUNIT["degree",0.0174532925199433]],
##     CS[ellipsoidal,2],
##         AXIS["latitude",north,
##             ORDER[1],
##             ANGLEUNIT["degree",0.0174532925199433]],
##         AXIS["longitude",east,
##             ORDER[2],
##             ANGLEUNIT["degree",0.0174532925199433]],
##     ID["EPSG",4326]]

The output above shows that our current dataframe, world_without_antarctica, is in the WGS 84 CRS. If you check our original dataframe, world, you will see that it has the same CRS.

By default, the map will use the coordinate system of the first layer that defines one (i.e. scanned in the order provided), or if none, fall back on WGS84 (latitude/longitude, the reference system used in GPS).

While choosing the right CRS can be complicated, changing the CRS in R is easy: add a coord_sf() layer where you specify the CRS you want to use, using the argument crs.

Here’s the Robinson projection/CRS:

ggplot() + 
  geom_sf(data = world_without_antarctica, 
          fill = "#669438", color = "#32481B", size = 0.25) +
  coord_sf(crs = st_crs("ESRI:54030")) +  # Robinson
  # Or use the name instead of the number
  # coord_sf(crs = "+proj=robin")
  ggtitle("Countries of the World", subtitle = "Robinson Projection")+
  theme_void()

What do you notice about the new map we made compared to the WGS 84 map?

Change the center of your map

The Orthographic Azimuthal projection is a good option if you want to choose the center of your map, though you won’t be able to see the other half of the world. For this, you will need to use a more complex bit of code for the crs argument, called a PROJ4 string. You will provide the proj alias, in this case ortho, and then the latitude (lat_0) and longitude (lon_0) of the “origin”, or center, of your map. In the example below, I have centered the map on my hometown of Lubbock, Texas.

Challenge 5: Look up the latitude and longitude of your hometown (or your current home), and change the PROJ4 string lat_0 and lon_0. Then change the title to reflect the place you are centering.

ggplot(data = world) +
  geom_sf(fill = "#669438", color = "#32481B", size = 0.25) +
    coord_sf(crs = "+proj=ortho +lat_0=33 +lon_0=-101 ") +
  ggtitle("Lubbock, TX as the Center of the World", subtitle = "Orthographic Azimuthal")+
  theme_void()

Congratulations! You have completed all the assignments for Week 1!

More resources

The resources in this section are not required for this course! They are provided in case you want to learn more. Feel free to come back to them after you finish the course.

More tutorials

This is a nice tutorial with a video to follow along. This tutorial requires you to download data that is provided in a .zip file. Tutorial: Visualizing Spatial Data

More tutorials that I used to create this week’s tutorial:

Drawing beautiful maps programmatically with R, sf and ggplot2 — Part 1: Basics

Drawing beautiful maps programmatically with R, sf and ggplot2 — Part 2: Layers

Drawing beautiful maps programmatically with R, sf and ggplot2 — Part 3: Layouts

Cartography Resources

Want to see what different projections look like compared to each other? Use this tool: Projection comparison

List of projections available (and their aliases!) using PROJ4 strings in R: Projections

More about using PROJ4 strings: Cartographic projection

Brewer Color Palette Interactive: Color Brewer 2.0

Need help determining the corners of your bounding box? Use this tool to draw your bounding box and get the locations of your corners. Just remember that in R, latitude and longitude is indicated as -90 to 90 and -180 to 180 for longitude

R Packages

If you want to learn more about RMarkdown, start with this book (written using RMarkdown!): RMarkdown: The Definitive Guide

If you want to learn more about doing non-spatial data science in R, this is the book to start with: R for Data Science